<template>
  <div>
    <Row class="header">
      <Col :span="20">
        <a style="margin-left: 10px">产品结构：</a>
      </Col>
      <Col :span="4">
        <Space>
          <a-button type="primary" preIcon="ion:ios-bookmarks-outline" @click="selectBom"
            >产品</a-button
          >
          <a-button preIcon="ion:camera-outline">截图</a-button>
        </Space>
      </Col>
    </Row>
    <PageWrapper :contentFullHeight="true" :contentBackground="true">
      <div class="mountNode" id="mountNode" ref="mountNode"></div>
    </PageWrapper>
    <Drawer
      title="产品信息"
      placement="right"
      :closable="true"
      :maskClosable="false"
      :width="600"
      v-model:visible="visible"
    >
      <BasicTable @register="registerTable" />
    </Drawer>
  </div>
</template>

<script setup lang="ts">
  import { getProductionDesignColumns, getProductionDesignConfig } from './tableData';
  import { Row, Col, Space, Drawer } from 'ant-design-vue';
  import { PageWrapper } from '/@/components/Page';
  import { BasicTable, useTable } from '/@/components/Table';
  import { onMounted, ref } from 'vue';
  import G6 from '@antv/g6';

  // 初始化数据
  const graph = ref(null);
  const mountNode = ref(null);
  const visible = ref(false);
  const data = ref({
    id: 'Root',
    name: 'Root Node',
    children: [
      {
        id: 'SubTreeNode1',
        name: 'SubTreeNode1',
        children: [
          {
            id: 'SubTreeNode1-1',
            name: 'SubTreeNode1-1',
          },
          {
            id: 'SubTreeNode1-2',
            name: 'SubTreeNode1-2',
          },
        ],
      },
      {
        id: 'SubTreeNode2',
        name: 'SubTreeNode2',
      },
    ],
  });

  // 初始化渲染
  const initTree = () => {
    // 自定义Icon
    const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
      return [
        ['M', x, y],
        ['a', r, r, 0, 1, 0, r * 2, 0],
        ['a', r, r, 0, 1, 0, -r * 2, 0],
        ['M', x + 2, y],
        ['L', x + 2 * r - 2, y],
      ];
    };
    const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
      return [
        ['M', x, y],
        ['a', r, r, 0, 1, 0, r * 2, 0],
        ['a', r, r, 0, 1, 0, -r * 2, 0],
        ['M', x + 2, y],
        ['L', x + 2 * r - 2, y],
        ['M', x + r, y - r + 2],
        ['L', x + r, y + r - 2],
      ];
    };
    G6.registerNode(
      'tree-node',
      {
        drawShape: function drawShape(cfg, group) {
          var rect = group.addShape('rect', {
            attrs: {
              fill: '#fff',
              stroke: '#666',
            },
          });
          var content = cfg.name.replace(/(.{19})/g, '$1\n');
          var text = group.addShape('text', {
            attrs: {
              text: content,
              x: 0,
              y: 0,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#666',
            },
          });
          const bbox = text.getBBox();
          const hasChildren = cfg.children && cfg.children.length > 0;
          if (hasChildren) {
            group.addShape('marker', {
              attrs: {
                x: bbox.maxX + 6,
                y: bbox.minX + bbox.height / 2 - 6,
                r: 6,
                symbol: COLLAPSE_ICON,
                stroke: '#666',
                lineWidth: 2,
              },
              className: 'collapse-icon',
            });
          }
          rect.attr({
            x: bbox.minX - 4,
            y: bbox.minY - 6,
            width: bbox.width + (hasChildren ? 26 : 8),
            height: bbox.height + 12,
          });
          return rect;
        },
      },
      'single-shape',
    );
    graph.value = new G6.TreeGraph({
      // 图的  DOM 容器，可以传入该 DOM 的 id 或者直接传入容器的 HTML 节点对象。
      container: 'mountNode',
      // 指定画布宽度，单位为 'px'。
      width: document.getElementById('mountNode').scrollWidth || 1600,
      // 指定画布高度，单位为 'px'。
      height: document.getElementById('mountNode').scrollHeight || 800,
      // 是否开启画布自适应。开启后图自动适配画布大小。
      fitView: true,
      //    v3.5.1 后支持。开启后，图将会被平移，图的中心将对齐到画布中心，但不缩放。优先级低于 fitView
      fitCenter: true,
      // 最小缩放比例
      minZoom: 1,
      // 最大缩放比例
      maxZoom: 2,
      // 指定边是否连入节点的中心
      linkCenter: true,
      // 设置画布的模式
      modes: {
        default: [
          {
            type: 'collapse-expand',
            onChange: function onChange(item, collapsed) {
              const data = item.get('model');
              const icon = item.get('group').findByClassName('collapse-icon');
              if (collapsed) {
                icon.attr('symbol', EXPAND_ICON);
              } else {
                icon.attr('symbol', COLLAPSE_ICON);
              }
              data.collapsed = collapsed;
              return true;
            },
          },
          'drag-canvas',
          'zoom-canvas',
        ],
      },
      // 默认状态下节点的配置，比如 type, size, color。会被写入的 data 覆盖。
      defaultNode: {
        shape: 'tree-node',
        anchorPoints: [
          [0, 0.5],
          [1, 0.5],
        ],
      },
      // 默认状态下边的配置，比如 type, size, color。会被写入的 data 覆盖。
      defaultEdge: {
        // 指定边的类型，可以是内置边的类型名称，也可以是自定义边的名称。默认为 'line'
        type: 'cubic-vertical',
        // 边的样式属性
        style: {
          // 边的颜色
          stroke: '#A3B1BF',
        },
      },
      // 布局配置项，使用 type 字段指定使用的布局方式
      layout: {
        // 布局名称
        type: 'compactBox',
        // layout 的方向。
        direction: 'LR', // H / V / LR / RL / TB / BT
        // 下面的参数都是一个节点，当存在某些奇葩点节点的时候，可以通过以下控制
        // 节点 id 的回调函数
        getId: function getId(d) {
          return d.id;
        },
        // 节点高度的回调函数
        getHeight: function getHeight() {
          return 16;
        },
        // 节点宽度的回调函数
        getWidth: function getWidth() {
          return 16;
        },
        // 节点纵向间距的回调函数
        getVGap: function getVGap() {
          return 20;
        },
        // 节点横向间距的回调函数
        getHGap: function getHGap() {
          return 80;
        },
      },
      // 动画
      animate: true,
    });
    // 初始化的图数据
    graph.value.data(data.value);
    // 根据提供的数据渲染视图。
    graph.value.render();
    // 让画布内容适应视口
    graph.value.fitView();
  };

  // 打开抽屉
  const selectBom = () => {
    visible.value = true;
  };

  // 初始化表格
  const [registerTable] = useTable({
    columns: getProductionDesignColumns(),
    bordered: true,
    showIndexColumn: true,
    showTableSetting: true, // 显示表格设置工具
    tableSetting: { fullScreen: true }, // 表格设置工具配置
    pagination: false,
    canResize: true,
    useSearchForm: true,
    formConfig: getProductionDesignConfig(), // 表单配置
  });
  onMounted(() => {
    initTree();
  });
</script>

<style lang="less" scoped>
  .mountNode {
    width: 100%;
    height: 700px;
  }

  .header {
    display: flex;
    align-items: center;
    width: 100%;
    height: 50px;
    margin: 20px 20px 0;
    background-color: #fff;
  }
</style>
